﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using Microsoft.Win32;
using System.Security.Principal;


// SkyDrive Documentation : Files and Folders
// http://msdn.microsoft.com/en-us/library/live/hh826531.aspx


namespace Coronox.SkyShell
{
    public static class SkyDriveAction
    {
        // Scopes and permissions (Live Connect)
        // http://msdn.microsoft.com/en-us/library/live/hh243646
       // static string m_Scope = "wl.skydrive_update wl.signin wl.offline_access wl.contacts_skydrive";
        //static string m_ClientID = "-";
        //static string m_ClientSecret = "-";
        //static Uri m_SignInUrl = new Uri(String.Format(@"https://login.live.com/oauth20_authorize.srf?client_id={0}&redirect_uri=https://login.live.com/oauth20_desktop.srf&response_type=code&scope={1}", m_ClientID, m_Scope));
        //static string m_AccessTokenUrl = String.Format(@"https://login.live.com/oauth20_token.srf?client_id={0}&client_secret={1}&redirect_uri=https://login.live.com/oauth20_desktop.srf&grant_type=authorization_code&code=", m_ClientID, m_ClientSecret);
        //static string m_RefreshTokenUrl = String.Format(@"https://login.live.com/oauth20_token.srf?client_id={0}&client_secret={1}&redirect_uri=https://login.live.com/oauth20_desktop.srf&grant_type=refresh_token&refresh_token=", m_ClientID, m_ClientSecret);

        static string m_ApiUrl = @"https://apis.live.net/v5.0/";
        static SkyDriveDirectoryInfo m_SkyDriveRoot = new SkyDriveDirectoryInfo() { ID = "me/skydrive" };

        static string m_authCode = string.Empty;
        static string m_AccessToken = string.Empty;
        static string m_RefreshToken = string.Empty;

        static LiveAccess _liveAccess = new LiveAccess();

        public static Uri SignInUrl
        {
            get
            {
                return _liveAccess.GetSignInUrl();
            }
        }

        public static string AuthCode
        {
            get
            {
                return m_authCode;
            }

            set
            {
                m_authCode = value;
            }
        }


        public static Dictionary<string, string> GetUserInfo()
        {
            if (string.IsNullOrEmpty(m_AccessToken))
                return null;

            return makeApiRequest(m_ApiUrl + "me?access_token=" + m_AccessToken);

        }


        private static Dictionary<string, string> makeApiRequest(string requestUrl)
        {
            WebClient wc = new WebClient();
            Dictionary<string, string> tokenData = new Dictionary<string, string>();
            string resultInfo = wc.DownloadString(new Uri(requestUrl));

            if (string.IsNullOrEmpty(resultInfo))
                return null;

            tokenData = deserializeJson(resultInfo);
            return tokenData;
        }

        public static string GetAccessTokenAndRefreshToken()
        {
            if (!string.IsNullOrEmpty(m_AccessToken))
            {
                return m_AccessToken;
            }
            else if (!string.IsNullOrEmpty(m_authCode))
            {
                WebClient wc = new WebClient();
                Dictionary<string, string> tokenData = new Dictionary<string, string>();
                string accessTokenUrl = _liveAccess.GetAccessTokenUrl();
                string resultInfo = wc.DownloadString(new Uri(accessTokenUrl + m_authCode));
                tokenData = deserializeJson(resultInfo);

                if (tokenData.ContainsKey("refresh_token"))
                {
                    SkyDriveAction.SetRegRefreshToken(tokenData["refresh_token"]);
                }

                m_AccessToken = tokenData.ContainsKey("access_token") ? tokenData["access_token"] : string.Empty;

                return m_AccessToken;
            }
            else
            {
                return string.Empty;
            }
        }


        public static bool RenewRefreshToken()
        {
            if (string.IsNullOrEmpty(SkyDriveAction.GetRegRefreshToken()))
            {
                return false;
            }

            WebClient wc = new WebClient();
            Dictionary<string, string> tokenData = new Dictionary<string, string>();


            string resultInfo = wc.DownloadString(new Uri(_liveAccess.GetRefreshTokenUrl() + SkyDriveAction.GetRegRefreshToken()));
            tokenData = deserializeJson(resultInfo);

            if (tokenData.ContainsKey("refresh_token"))
            {
                SkyDriveAction.SetRegRefreshToken(tokenData["refresh_token"]);
            }

            if (tokenData.ContainsKey("access_token"))
            {
                m_AccessToken = tokenData["access_token"];
            }

            return true;
        }


        private static Dictionary<string, string> deserializeJson(string json)
        {
            var jss = new JavaScriptSerializer();
            var d = jss.Deserialize<Dictionary<string, string>>(json);
            return d;
        }

        public static SkyDriveDirectoryInfo GetSkyDriveFolder(string mLocalComputerPath)
        {
            if (string.IsNullOrEmpty(GetAccessTokenAndRefreshToken()))
            {
                return null;
            }

            if (string.IsNullOrEmpty(mLocalComputerPath))
            {
                return null;
            }

            List<string> mLocalPathFolderList = mLocalComputerPath.Split('\\').ToList();
            int index = mLocalPathFolderList.IndexOf("SkyDrive");

            if (!(index > 0))
            {
                return null;
            }

            mLocalPathFolderList.RemoveRange(0, index + 1);
            SkyDriveDirectoryInfo SkydriveFolder = GetSkydriveFolderIDRecurive(mLocalPathFolderList, m_SkyDriveRoot);

            return SkydriveFolder;
        }


        public static string GetSkyDriveFolderID(string mLocalComputerPath)
        {
            if (GetSkyDriveFolder(mLocalComputerPath) == null)
                return String.Empty;
            else
                return GetSkyDriveFolder(mLocalComputerPath).ID;
        }


        private static SkyDriveDirectoryInfo GetSkydriveFolderIDRecurive(List<string> mLocalPathFolderList, SkyDriveDirectoryInfo currentSkydriveFolder)
        {
            WebClient wc = new WebClient();
            //string result = (await Task<string>.Factory.StartNew(() => wc.DownloadString(new Uri(apiUrl + currentSkydriveFolder + "/files?access_token=" + App.Current.Properties["access_token"])))).ToUTF8();
            string result = wc.DownloadString(new Uri(m_ApiUrl + currentSkydriveFolder.ID + "/files?access_token=" + GetAccessTokenAndRefreshToken())).ToUTF8();

            System.Web.Script.Serialization.JavaScriptSerializer oconvert = new System.Web.Script.Serialization.JavaScriptSerializer();

            SkyDriveDirectoryInfoData SkyFolders = oconvert.Deserialize<SkyDriveDirectoryInfoData>(result);

            SkyDriveDirectoryInfo newSkydrivFolderObject;

            if (mLocalPathFolderList.Count() > 0 && SkyFolders != null)
            {
                newSkydrivFolderObject = SkyFolders.Data.Where(f => f.ID.Contains("folder") && f.Name == mLocalPathFolderList[0]).FirstOrDefault();
                mLocalPathFolderList.RemoveAt(0);

                if (mLocalPathFolderList.Count() > 0)
                {
                    return GetSkydriveFolderIDRecurive(mLocalPathFolderList, newSkydrivFolderObject);
                }
                else
                {
                    return newSkydrivFolderObject;
                }
            }

            return null;
        }

        public static string GetSkyDriveFolderUri(string strSkyDriveObject)
        {
            string mUriSkyDriveFolderID = strSkyDriveObject.Replace("folder.", "");
            string[] mUriRootFolderList = mUriSkyDriveFolderID.ToUpper().Split('.');
            if (mUriRootFolderList.Count() != 2)
                return string.Empty;

            return string.Format("https://skydrive.live.com/?cid={0}#cid={1}&id={2}", mUriSkyDriveFolderID, mUriRootFolderList[0], mUriRootFolderList[1]);
        }


        //public static string GetReadonlySharedLink(string strSkyDriveObject)
        //{
        //    WebClient wc = new WebClient();
        //    string result = wc.DownloadString(new Uri(m_ApiUrl + strSkyDriveObject + "/shared_read_link?access_token=" + GetAccessTokenAndRefreshToken()));

        //    System.Web.Script.Serialization.JavaScriptSerializer oconvert = new System.Web.Script.Serialization.JavaScriptSerializer();

        //    if (string.Empty == result)
        //        return string.Empty;

        //    Dictionary<string, string> resultdata = oconvert.Deserialize<Dictionary<string, string>>(result);

        //    if (resultdata == null)
        //        return string.Empty;

        //    return resultdata["link"];
        //}


        //public static string GetEditableSharedLink(string strSkyDriveObject)
        //{
        //    WebClient wc = new WebClient();
        //    string result = wc.DownloadString(new Uri(m_ApiUrl + strSkyDriveObject + "/shared_edit_link?access_token=" + GetAccessTokenAndRefreshToken()));

        //    System.Web.Script.Serialization.JavaScriptSerializer oconvert = new System.Web.Script.Serialization.JavaScriptSerializer();

        //    if (string.Empty == result)
        //        return string.Empty;

        //    Dictionary<string, string> resultdata = oconvert.Deserialize<Dictionary<string, string>>(result);

        //    if (resultdata == null)
        //        return string.Empty;

        //    return resultdata["link"];
        //}



        public static bool SetRegRefreshToken(string RefreshToken)
        {
            var subkey = Registry.CurrentUser.OpenSubKey("Software\\Coronox\\SkyShellEx", RegistryKeyPermissionCheck.ReadWriteSubTree);
            if (subkey == null)
            {
                subkey = CreateRegistryKeys();
            }

            if (subkey == null)
                return false;

            if (GetRegRememberLogin())
            {
                subkey.SetValue("RefreshToken", Encryption.EncryptString(RefreshToken, "simple§3noit$5crEn"));
            }
            else
            {
                subkey.SetValue("RefreshToken", string.Empty);
                m_RefreshToken = RefreshToken;
            }
            return true;
        }


        public static string GetRegRefreshToken()
        {
            var subkey = Registry.CurrentUser.OpenSubKey("Software\\Coronox\\SkyShellEx", RegistryKeyPermissionCheck.ReadWriteSubTree);

            if (subkey == null)
                return string.Empty;

            if (!subkey.GetValueNames().Contains("RefreshToken"))
                return string.Empty;

            if (GetRegRememberLogin())
            {
                if (!string.IsNullOrEmpty(subkey.GetValue("RefreshToken").ToString()))
                    return Encryption.DecryptString(subkey.GetValue("RefreshToken").ToString(), "simple§3noit$5crEn");
                else
                    return string.Empty;
            }
            else
            {
                return m_RefreshToken;
            }
        }


        public static bool SetRegRememberLogin(bool mRememberLogin)
        {
            var subkey = Registry.CurrentUser.OpenSubKey("Software\\Coronox\\SkyShellEx", RegistryKeyPermissionCheck.ReadWriteSubTree);
            if (subkey == null)
            {
                subkey = CreateRegistryKeys();
            }

            if (subkey == null)
                return false;

            subkey.SetValue("RememberLogin", mRememberLogin);

            return true;
        }


        public static bool GetRegRememberLogin()
        {
            var subkey = Registry.CurrentUser.OpenSubKey("Software\\Coronox\\SkyShellEx", RegistryKeyPermissionCheck.ReadWriteSubTree);

            if (subkey == null)
                return false;

            if (!subkey.GetValueNames().Contains("RememberLogin"))
                return false;

            return bool.Parse(subkey.GetValue("RememberLogin").ToString());
        }


        private static RegistryKey CreateRegistryKeys()
        {
            var subKey = Registry.CurrentUser.OpenSubKey("Software", RegistryKeyPermissionCheck.ReadWriteSubTree);
            if (subKey == null)
                return null;

            var CoronoxKey = subKey.CreateSubKey("Coronox");
            if (CoronoxKey == null)
                return null;

            var SkyShellExKey = CoronoxKey.CreateSubKey("SkyShellEx");
            if (SkyShellExKey == null)
                return null;

            return SkyShellExKey;
        }


        // C# 5.0 Async function call
        //public static async Task<string> getSharedFolderUrlAsync(string strSkyDriveObject)
        //{
        //    return await Task.Factory.StartNew(() => getSharedFolderUrl(strSkyDriveObject));
        //}

    }
}
